﻿#include "ui_camerasctrl.h"  // 避免 lib 该头文件 被第三方依赖，声明为指针形式
#include "../EagleDeviceMgr.h"
#include "configInterface.h"
#include "camerasctrl.h"
#include <iosfwd>
#include <strstream>
#include <QFile>

#ifdef _WIN32
#pragma execution_character_set("utf-8")
#endif

static QString last_operate_camera;
static std::strstream  g_strStream;
CamLog *g_streamLog = NULL;
static camerasCtrl* g_Form = NULL;


camerasCtrl::camerasCtrl(QWidget* parent)
	:QDialog(parent)
	, ui(new Ui::camerasCtrl)
{
	ui->setupUi(this);
	ui->label_tips->setText("");
	g_Form = this;
	g_streamLog = CreateCamLog(g_strStream.rdbuf());
	
	std::map<wstring, CameraPlugin*> &cameras = CameraPluginMgr::getInstance()->GetAllCameras();
	for (auto it = cameras.begin(); it != cameras.end(); it++)
	{
		ui->cmb_camNam->addItem(QString::fromStdWString(GetCameraBasic(it->second)));
	}

	if (last_operate_camera.isEmpty())
	{
		ui->cmb_camNam->setCurrentIndex(0);
		current_camera = ui->cmb_camNam->currentText();
	}
	else
	{
		ui->cmb_camNam->setCurrentText(last_operate_camera);
		current_camera = last_operate_camera;
	}
	
	std::vector<int> devices;
	wchar_t name[32] = { '\0' };
	CEagleDeviceMgr::GetInstance()->GetAllDevice(devices);

	for (auto dev_it = devices.begin(); dev_it != devices.end(); dev_it++)
	{
		EagleControl_GetDeviceName(*dev_it, name);
		ui->cmb_dev->addItem(QString::fromWCharArray(name));
	}
	ui->cmb_dev->setCurrentIndex(-1);

	m_layInterface = new QVBoxLayout(ui->wgt_interfaces);
	m_laySubInterface = new QVBoxLayout(ui->wgt_subinterfaces);
	m_laySubInterface->setSpacing(0);
	m_layInterface->setSpacing(2);
	//  初始化完毕连接信号 [11/28/2016 ejitec]
	connect(ui->cmb_dev, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
		this, &camerasCtrl::on_cmbDevChange);

	connect(ui->cmb_camNam, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
		this, &camerasCtrl::on_cmbCamChange);
	// 
	connect(ui->btn_send, &QPushButton::clicked, this, &camerasCtrl::on_btnCmdCLick);
	// 回车 后自动 发送自定义命令
	connect(ui->cmdText, &QLineEdit::returnPressed, this, [this]()
	{
		ui->btn_send->clicked();
	});

	if (!devices.empty())
	{
		ui->cmb_dev->setCurrentIndex(0);
	}
	else
	{
		emit ui->cmb_camNam->currentIndexChanged(0);
	}

	
	ui->splitter->setStretchFactor(0, 0);
	ui->splitter->setStretchFactor(1, 1);

	QFile f(qApp->applicationDirPath() + "/custom_cmd");
	if (!f.exists())
	{
		ui->wgt_log->hide();
	}

	ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("确定"));
	connect(ui->checkBox_hex, &QCheckBox::stateChanged, this, [this](int nStat)
	{

		if (ui->cmdText->text().isEmpty())
		{
			return;
		}

		QString strText = ui->cmdText->text();

		if (nStat == Qt::Checked)
		{
			ui->cmdText->setText(QByteArray(qPrintable(strText)).toHex());
		}
		else
		{
			ui->cmdText->setText(QByteArray::fromHex(qPrintable(strText)));
		}
	});

}

CameraPlugin *camerasCtrl::GetCurrentCamera()
{
	return CameraPluginMgr::getInstance()->GetCamera(current_camera.toStdWString());
}

camerasCtrl::~camerasCtrl()
{
	delete g_streamLog;
	g_streamLog = NULL;
}

void camerasCtrl::on_cmbDevChange(int nIndex)
{
	int selection = nIndex;
	if (selection == -1)
		return;
	std::vector<int> devices;
	CEagleDeviceMgr::GetInstance()->GetAllDevice(devices);
	int device_id = devices.at(selection);
	ui->cmb_ccdNam->clear();
	int camera_num = 0;
	EagleControl_GetMaxCameraNumber(device_id, &camera_num);
	wchar_t cam_name[32] = { '\0' };
	valid_ccd_serials.clear();
	for (int i = 1; i <= camera_num; i++)
	{
		if (EagleControl_IsCameraValid(device_id, i))
		{
			EagleControl_GetCameraName(device_id, i, cam_name);
			ui->cmb_ccdNam->addItem(QString::fromWCharArray(cam_name));
			valid_ccd_serials.push_back(i);
		}
	}

	ui->cmb_ccdNam->setCurrentIndex(-1);
// 	connect(ui->cmb_ccdNam, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
// 		this, &camerasCtrl::on_cmbCCDChange);

	if (camera_num != 0)
	{
		ui->cmb_ccdNam->setCurrentIndex(0);
		emit ui->cmb_camNam->currentIndexChanged(ui->cmb_camNam->currentIndex());
	}
}

void camerasCtrl::on_cmbCCDChange(int nIndex)
{
	int ccd_serial = nIndex;
	int selection = ui->cmb_dev->currentIndex();
	if (ccd_serial == -1 || selection == -1)
		return;
	std::vector<int> devices;
	CEagleDeviceMgr::GetInstance()->GetAllDevice(devices);
	int device_id = devices.at(selection);

	CameraPlugin *cur_camera = GetCurrentCamera();
	cur_camera->DisConnect();
	cur_camera->Connect(device_id, valid_ccd_serials.at(ccd_serial));
}

void camerasCtrl::on_cmbCamChange(int nIndex)
{
	DestroryAllInterface();
	DestroryAllSubInterface();

	current_camera = ui->cmb_camNam->currentText();
	try
	{
		CameraPlugin *cur_camera = GetCurrentCamera();
		if (cur_camera) {
			last_operate_camera = current_camera;
			long serial_rate = cur_camera->GetSerialRate();
			//TODO:Set serial rate to eagle device
			std::vector<CameraInterface*>& interfaces = cur_camera->GetSupportInterface();
			if (!interfaces.empty()) 
			{
				for (auto it = interfaces.begin(); it != interfaces.end(); it++) 
				{
					if ((*it)->GetName() == CameraKeyInterfaceName)
						continue;
					// 左列单相机 所有功能按钮  每个按钮响应 所有 sub功能页面创建[11/24/2016 ejitec]
					InterfaceButton *interfaceButton = new InterfaceButton(ui->wgt_interfaces, *it,
						// 占位2个 输入2个参数 [11/29/2016 ejitec]
						std::bind(&camerasCtrl::DrawComment, this, std::placeholders::_1, std::placeholders::_2));
					m_layInterface->addWidget(interfaceButton, 0);
				}

				m_layInterface->addStretch(0);
			}

			int ccd_serial = ui->cmb_ccdNam->currentIndex();
			int selection = ui->cmb_dev->currentIndex();
			if (ccd_serial != -1 || selection != -1)
			{
				std::vector<int> devices;
				CEagleDeviceMgr::GetInstance()->GetAllDevice(devices);
				int device_id = devices.at(selection);
				cur_camera->DisConnect();
				cur_camera->Connect(device_id, valid_ccd_serials.at(ccd_serial));
				g_streamLog->WWrite((QString("Select Camera:%1").arg(current_camera)).toStdWString().c_str());
			}
		}
	}
	catch (std::runtime_error&)
	{
		//TODO::some log or other things
	}
}

void camerasCtrl::DrawComment(std::wstring comment, bool read_only)
{
	ui->label_tips->setText(QString::fromStdWString(comment));
	ui->label_tips->setEnabled(!read_only);
}

void camerasCtrl::accept()
{
	QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
	qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
	for (auto it = set_callbacks.begin(); it != set_callbacks.end(); it++) 
	{
		(*it)();
	}
	QDialog::accept();
	QApplication::restoreOverrideCursor();
}

void camerasCtrl::on_btnCmdCLick()
{
	long slength = 0;
	unsigned char buf[128] = { '\0' };
	std::string cmd = "";
	CameraPlugin *camera = GetCurrentCamera();
	if (camera) {
		cmd += camera->GetStartCode();
	}
	cmd += ui->cmdText->text().toStdString();
	if (camera) 
	{
		cmd += camera->GetEndCode();
	}
	
	SerialPort Serial;
	std::vector<int> device_list;
	GetAllDevice(device_list);
	int device_id = -1;
	int dev_sel = ui->cmb_dev->currentIndex();
	int cam_sel = ui->cmb_ccdNam->currentIndex();
	if (-1 == dev_sel || -1 == dev_sel)
		return;

	Serial.connect(device_list.at(dev_sel), cam_sel + 1, "base", camera->GetSerialRate());
	slength = cmd.length();
	Serial.sendArray(cmd.c_str(), cmd.length());
	Serial.getArray(buf, 128);
	Serial.disconnect();
}

void camerasCtrl::DestroryAllSubInterface()
{
	//
	QList<QWidget*> childs = ui->wgt_subinterfaces->findChildren<QWidget*>();

	for (auto it:childs)
	{
		it->deleteLater();
	}
	
	QLayoutItem* child = nullptr;  // 删除所有的 strech
	while ((child = m_laySubInterface->takeAt(0)) != 0)
 	{
 	 	delete child;
 	 	child = nullptr;
 	}

	ui->wgt_subinterfaces->update();
}

void camerasCtrl::DestroryAllInterface()
{
	QList<QWidget*> childs = ui->wgt_interfaces->findChildren<QWidget*>();

	for (auto it : childs)
	{
		it->deleteLater();
	}

	QLayoutItem* child = nullptr;  // 删除所有的 strech
	while ((child = m_layInterface->takeAt(0)) != 0)
	{
		delete child;
		child = nullptr;
	}
	
	ui->wgt_interfaces->update();
}

QWidget* camerasCtrl::GetSubInterfacePanel()
{
	return ui->wgt_subinterfaces;
}

QVBoxLayout* camerasCtrl::GetSubInterfaceLayOut()
{
	return m_laySubInterface;
}


//////////////////////////////////////////////////////////////////////////
// InterfaceButton  [11/28/2016 ejitec]

void InterfaceButton::on_interfacebtnClick()
{
	bool read_only = true;
	g_Form->DestroryAllSubInterface(); // 清空上次创建的 所有相机属性控件
	std::vector<camerasCtrl::sub_interface_panel_set_callback> sub_interface_set_callbacks;
	QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
	//qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
	std::vector<SubInterface*> &subInterfaces = _cameraInterface->GetAllSubInterfaces();
	if (!subInterfaces.empty())
	{
		//先查找是否有CamValueInteger，先获取其值
		for (auto it = subInterfaces.begin(); it != subInterfaces.end(); it++)
		{
			if ((*it)->GetValueType() == CamValueInteger)
			{
				CAM_INTERFACE_VALUE_TYPE V;
				(*it)->Get(V);
			}
		}
		
		for (auto it = subInterfaces.begin(); it != subInterfaces.end(); it++)
		{
			QWidget *sub_panel = NULL;
			switch ((*it)->GetValueType()){
			case CamValueBool:
				sub_panel = new ValueBoolPanel(g_Form->GetSubInterfacePanel(), dynamic_cast<BoolSubInterface*>((*it)));
				sub_interface_set_callbacks.push_back(std::bind(&ValueBoolPanel::Set, dynamic_cast<ValueBoolPanel*>(sub_panel)));
				break;
			case CamValueEnum:
				sub_panel = new ValueEnumPanel(g_Form->GetSubInterfacePanel(), dynamic_cast<EnumSubInterface*>((*it)));
				sub_interface_set_callbacks.push_back(std::bind(&ValueEnumPanel::Set, dynamic_cast<ValueEnumPanel*>(sub_panel)));
				break;
			case CamValueRangeInteger:
				sub_panel = new ValueRangeIntegerPanel(g_Form->GetSubInterfacePanel(), dynamic_cast<IntegerRangeSubInterface*>((*it)));
				sub_interface_set_callbacks.push_back(std::bind(&ValueRangeIntegerPanel::Set, dynamic_cast<ValueRangeIntegerPanel*>(sub_panel)));
				break;
			case CamValueRangeFloat:
				break;
			case CamValueText:
				sub_panel = new ValueTextPanel(g_Form->GetSubInterfacePanel(), dynamic_cast<TextSubInterface*>((*it)));
				break;
			case CamValueInteger:
				sub_panel = new DummyPanel(g_Form->GetSubInterfacePanel(), *it);
				sub_interface_set_callbacks.push_back(std::bind(&DummyPanel::Set, dynamic_cast<DummyPanel*>(sub_panel)));
				break;
			default:
				break;
			}
			if (sub_panel)
			{
				g_Form->GetSubInterfaceLayOut()->addWidget(sub_panel, 0);
			}
			if ((*it)->GetAccessMode() != CamAccessR) {
				read_only = false;
			}
		}
		g_Form->GetSubInterfaceLayOut()->addStretch(0);

		if (_cameraInterface->IsInterfaceFinalSetValid())
		{
			sub_interface_set_callbacks.push_back(std::bind(&CameraInterface::FinalSet, dynamic_cast<CameraInterface*>(_cameraInterface)));
		}
	}
	QApplication::restoreOverrideCursor();
	// 单个功能 按钮的单击 显示 操作文本
	callback(_cameraInterface->GetComment(), read_only);
	g_Form->RegisterButtonClickCallbacks(sub_interface_set_callbacks);
	g_Form->update();
}

InterfaceButton::InterfaceButton(QWidget *parent, CameraInterface *cameraInterface, button_click_callback cb)
:QPushButton(parent), _cameraInterface(cameraInterface), callback(cb)
{
	setText(QString::fromStdWString(_cameraInterface->GetName()));
	setToolTip(QString::fromStdWString(_cameraInterface->GetComment()));
	connect(this, &QPushButton::clicked, this, &InterfaceButton::on_interfacebtnClick);
}


